use crate::{Solution, SolutionPair};
use std::collections::HashSet;
use std::fs::read_to_string;

fn get_marker(data_buffer: &str, marker_size: usize) -> usize {
    let mut marker_window: Vec<char> = Vec::new();
    let mut marker_end_index = 0;
    for (index, current_char) in data_buffer.chars().enumerate() {
        if marker_window.len() < marker_size {
            marker_window.push(current_char);
            continue;
        }

        if marker_window.len() > marker_window.iter().collect::<HashSet<_>>().len() {
            marker_window.remove(0);
            marker_window.push(current_char);
            continue;
        }

        marker_end_index = index;
        break;
    }

    marker_end_index
}

fn solve_part1(input: &str) -> usize {
    get_marker(input, 4)
}

fn solve_part2(input: &str) -> usize {
    get_marker(input, 14)
}

pub fn solve() -> SolutionPair {
    let input = read_to_string("input/day06.txt").unwrap();

    let sol1 = solve_part1(&input);
    let sol2 = solve_part2(&input);

    (Solution::from(sol1), Solution::from(sol2))
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn part1() {
        assert_eq!(solve_part1("mjqjpqmgbljsphdztnvjfqwrcgsmlb"), 7);
        assert_eq!(solve_part1("bvwbjplbgvbhsrlpgdmjqwftvncz"), 5);
        assert_eq!(solve_part1("nppdvjthqldpwncqszvftbrmjlhg"), 6);
        assert_eq!(solve_part1("nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg"), 10);
        assert_eq!(solve_part1("zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw"), 11);
    }

    #[test]
    fn part2() {
        assert_eq!(solve_part2("mjqjpqmgbljsphdztnvjfqwrcgsmlb"), 19);
        assert_eq!(solve_part2("bvwbjplbgvbhsrlpgdmjqwftvncz"), 23);
        assert_eq!(solve_part2("nppdvjthqldpwncqszvftbrmjlhg"), 23);
        assert_eq!(solve_part2("nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg"), 29);
        assert_eq!(solve_part2("zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw"), 26);
    }
}
